package com.ruoyi.cat.service.impl;


import com.ruoyi.cat.domain.CatBasedataTable;
import com.ruoyi.cat.domain.CatTradedetailTable;
import com.ruoyi.cat.domain.CatUserbasicTable;
import com.ruoyi.cat.domain.VO.ApiOracleVO;
import com.ruoyi.cat.domain.VO.OrderQueryVO;
import com.ruoyi.cat.domain.VO.SysOracleVO;
import com.ruoyi.cat.service.ICatBasedataTableService;
import com.ruoyi.cat.service.ICatTradedetailTableService;
import com.ruoyi.cat.service.ICatUserbasicTableService;
import com.ruoyi.cat.service.OracleService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.HttpRequestProxy;
import com.ruoyi.common.utils.OrderUtil;
import com.ruoyi.common.wxpay.LinWxPayConfigSample;
import com.ruoyi.common.wxpay.WXPay;
import com.ruoyi.common.wxpay.WXPayConstants;
import com.ruoyi.common.wxpay.WXPayUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Service
public class OracleServiceImpl implements OracleService {

    @Autowired
    private ICatBasedataTableService catBasedataTableService;

    @Value("${wx.pay-callback-host}")
    private String payCallbackHost;

    @Value("${wx.pay-callback-path}")
    private String payCallbackPath;

    private static LinWxPayConfigSample linWxPayConfig = new LinWxPayConfigSample();

    @Autowired
    private ICatTradedetailTableService catTradedetailTableService;

    @Autowired
    private ICatUserbasicTableService iCatUserbasicTableService;


    @Override
    public AjaxResult scanCodePayOrder(SysOracleVO sysOracleVO) {
        CatBasedataTable catBasedataTable = catBasedataTableService.selectCatBasedataTableById(1L);
        BigDecimal regis = OrderUtil.calculateProduct(sysOracleVO.getTargetNum(), catBasedataTable.getBaseCost());
        String orderNo =  OrderUtil.makeOrderNo();
        Map<String, String>  map = makePreOrderParams(regis,orderNo ,"NATIVE");
        CatTradedetailTable catTradedetailTable = new CatTradedetailTable();
        catTradedetailTable.setOrderNo(orderNo);
       // catTradedetailTable.setActivityId(sysOracleVO.getId());
        catTradedetailTable.setTradeNum(regis);
        catTradedetailTable.setTradeTitle("购买文章金额");
        catTradedetailTable.setTradeType("1");
        catTradedetailTableService.insertCatTradedetailTable(catTradedetailTable);
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult apiCodePayOrder(ApiOracleVO apiOracleVO) {
        CatUserbasicTable catUserbasicTable = iCatUserbasicTableService.selectCatUserbasicTableById(apiOracleVO.getUserId());
        CatBasedataTable catBasedataTable = catBasedataTableService.selectCatBasedataTableById(1L);
        BigDecimal regis = OrderUtil.calculateProduct(apiOracleVO.getTargetNum(), catBasedataTable.getBaseCost());
        String orderNo =  OrderUtil.makeOrderNo();
        Map<String, String>  map = apiMakePreOrderParams(regis,orderNo ,"NATIVE",catUserbasicTable.getOpenId());
        CatTradedetailTable catTradedetailTable = new CatTradedetailTable();
        catTradedetailTable.setOrderNo(orderNo);
        catTradedetailTable.setActivityId(apiOracleVO.getId());
        catTradedetailTable.setTradeNum(regis);
        catTradedetailTable.setTradeTitle("购买文章金额");
        catTradedetailTable.setTradeType("1");
        catTradedetailTableService.insertCatTradedetailTable(catTradedetailTable);
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult orderQuery(OrderQueryVO apiOracleVO) {
        WXPay wxPay = this.assembleWxPayConfig();
        Map<String, String> data = new HashMap<>();
        try {
            data.put("appid",OracleServiceImpl.linWxPayConfig.getAppID() );
            data.put("mch_id", OracleServiceImpl.linWxPayConfig.getMchID());
            data.put("transaction_id", apiOracleVO.getOrderNo());
            data.put("nonce_str", WXPayUtil.generateNonceStr());
            String sign = WXPayUtil.generateSignature(data, OracleServiceImpl.linWxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
            data.put("sign",sign);
            Map<String, String> wxOrder = wxPay.unifiedOrder(data);
            if (wxOrder.get("trade_state").equals("SUCCESS")){
                CatTradedetailTable catTradedetailTable = new CatTradedetailTable();
                catTradedetailTable.setOrderNo(apiOracleVO.getOrderNo());
                catTradedetailTable.setStatus("1");
                catTradedetailTableService.insertCatTradedetailTable(catTradedetailTable);
            }
            return AjaxResult.success(wxOrder);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Map<String, String> apiMakePreOrderParams(BigDecimal serverFinalPrice, String orderNo,String tradeType,String openid) {
        String payCallbackUrl = payCallbackHost + payCallbackPath;
        WXPay wxPay = this.assembleWxPayConfig();
        Map<String, String> data = new HashMap<>();
        data.put("device_info", "Sleeve");
        data.put("fee_type", "CNY");
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("body", "购买了文章");
        data.put("out_trade_no", orderNo);
        data.put("total_fee", OrderUtil.yuanToFenPlainString(serverFinalPrice));
        data.put("spbill_create_ip", HttpRequestProxy.getRemoteRealIp());
        data.put("notify_url", payCallbackUrl);
        data.put("trade_type", "JSAPI");
        data.put("openid", openid);
        String sign ="";
        try {
            sign = WXPayUtil.generateSignature(data, OracleServiceImpl.linWxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
            data.put("sign",sign);
            Map<String, String> wxOrder = wxPay.unifiedOrder(data);
            Map<String, String> stringMap = makePaySignature(wxOrder);
            return stringMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    private Map<String, String> makePreOrderParams(BigDecimal serverFinalPrice, String orderNo,String tradeType) {
        String payCallbackUrl = payCallbackHost + payCallbackPath;
        WXPay wxPay = this.assembleWxPayConfig();
        Map<String, String> data = new HashMap<>();
        data.put("device_info", "Sleeve");
        data.put("fee_type", "CNY");
        data.put("nonce_str", WXPayUtil.generateNonceStr());
        data.put("body", "购买了文章");
        data.put("out_trade_no", orderNo);
        data.put("total_fee", OrderUtil.yuanToFenPlainString(serverFinalPrice));
        data.put("spbill_create_ip", HttpRequestProxy.getRemoteRealIp());
        data.put("notify_url", payCallbackUrl);
        data.put("trade_type", tradeType);
        String sign ="";
        try {
            sign = WXPayUtil.generateSignature(data, OracleServiceImpl.linWxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
            data.put("sign",sign);
            Map<String, String> wxOrder = wxPay.unifiedOrder(data);
            Map<String, String> stringMap = makePaySignature(wxOrder);
            return stringMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Map<String, String> makePaySignature(Map<String, String> wxOrder) {
        Map<String, String> wxPayMap = new HashMap<>();
        String packages = "prepay_id=" + wxOrder.get("prepay_id");
        wxPayMap.put("appId", OracleServiceImpl.linWxPayConfig.getAppID());
        wxPayMap.put("timeStamp", OrderUtil.timestamp10());
        wxPayMap.put("nonceStr", RandomStringUtils.randomAlphanumeric(32));
        wxPayMap.put("package", packages);
        wxPayMap.put("signType", "HMAC-SHA256");
        wxPayMap.put("out_trade_no",wxOrder.get("out_trade_no"));
        if (null != wxOrder.get("code_url")){
            wxPayMap.put("code_url", wxOrder.get("code_url"));
        }
        String sign ="";
        try {
            sign = WXPayUtil.generateSignature(wxPayMap, OracleServiceImpl.linWxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Map<String, String> miniPayParams = new HashMap<>();

        miniPayParams.put("paySign", sign);
        miniPayParams.putAll(wxPayMap);
        miniPayParams.remove("appId");
        return miniPayParams;
    }


    public WXPay assembleWxPayConfig() {
        WXPay wxPay = null;
        try {
            wxPay = new WXPay(OracleServiceImpl.linWxPayConfig);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return wxPay;
    }
}
